package com.sokal.easycare.modules.sys.service;

import java.util.Collection;
import java.util.List;

import org.apache.shiro.session.Session;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sokal.easycare.common.persistence.Page;
import com.sokal.easycare.common.security.Digests;
import com.sokal.easycare.common.security.shiro.session.SessionDAO;
import com.sokal.easycare.common.service.BaseService;
import com.sokal.easycare.common.service.ServiceException;
import com.sokal.easycare.common.utils.CacheUtils;
import com.sokal.easycare.common.utils.Encodes;
import com.sokal.easycare.common.utils.StringUtils;
import com.sokal.easycare.modules.payment.dao.UserAccountDao;
import com.sokal.easycare.modules.payment.entity.UserAccount;
import com.sokal.easycare.modules.position.entity.Duty;
import com.sokal.easycare.modules.sys.dao.MenuDao;
import com.sokal.easycare.modules.sys.dao.RoleDao;
import com.sokal.easycare.modules.sys.dao.UserDao;
import com.sokal.easycare.modules.sys.dao.UserRealnameAuthDao;
import com.sokal.easycare.modules.sys.entity.MainUser;
import com.sokal.easycare.modules.sys.entity.Menu;
import com.sokal.easycare.modules.sys.entity.Office;
import com.sokal.easycare.modules.sys.entity.Role;
import com.sokal.easycare.modules.sys.entity.UserRealnameAuth;
import com.sokal.easycare.modules.sys.utils.LogUtils;
import com.sokal.easycare.modules.sys.utils.UserUtils;

/**
 * 系统管理，安全相关实体的管理类,包括用户、角色、菜单.
 * 
 * @author easycare
 * @version 2017-12-05
 */
@Service
@Transactional(readOnly = true)
public class SystemService extends BaseService implements InitializingBean {

	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;

	@Autowired
	private UserDao userDao;
	@Autowired
	private UserRealnameAuthDao userRealnameAuthDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MenuDao menuDao;
	@Autowired
	private SessionDAO sessionDao;
	

	@Autowired
	private UserAccountDao accountDao;

	public SessionDAO getSessionDao() {
		return sessionDao;
	}


	// -- User Service --//

	/**
	 * 获取用户
	 * 
	 * @param id
	 * @return
	 */
	public MainUser getUser(String id) {
		return UserUtils.get(id);
	}
	
	public UserRealnameAuth getUserRealnameAuth(String userId)
	{
		return userRealnameAuthDao.getByUserId(userId);
	}

	/**
	 * 根据登录名获取用户
	 * 
	 * @param loginName
	 * @return
	 */
	public MainUser getUserByLoginName(String loginName) {
		Page<MainUser> page = new Page<MainUser>();
		MainUser mainUser = new MainUser();
		Duty duty = new Duty();
		duty.setId("da7273f08e414e78a5c9feed5f8e724d");
		mainUser.setDuty(duty);
		// 设置分页参数
		mainUser.setPage(page);
		// 执行分页查询
		page.setList(userDao.findUserByDutyId(mainUser));
		return UserUtils.getByLoginName(loginName);
	}

	public Page<MainUser> findUser(Page<MainUser> page, MainUser mainUser) {
		// 设置分页参数
		mainUser.setPage(page);
		// 执行分页查询
		page.setList(userDao.findList(mainUser));
		return page;
	}

	/**
	 * 无分页查询人员列表
	 * 
	 * @param mainUser
	 * @return
	 */
	public List<MainUser> findUser(MainUser mainUser) {
		List<MainUser> list = userDao.findList(mainUser);
		return list;
	}

	/**
	 * 通过部门ID获取用户列表，仅返回用户id和name（树查询用户时用）
	 * 
	 * @param user
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<MainUser> findUserByOfficeId(String officeId) {
		List<MainUser> list = (List<MainUser>) CacheUtils.get(UserUtils.USER_CACHE,
				UserUtils.USER_CACHE_LIST_BY_OFFICE_ID_ + officeId);
		if (list == null) {
			MainUser mainUser = new MainUser();
			mainUser.setOffice(new Office(officeId));
			list = userDao.findUserByOfficeId(mainUser);
			CacheUtils.put(UserUtils.USER_CACHE, UserUtils.USER_CACHE_LIST_BY_OFFICE_ID_ + officeId, list);
		}
		return list;
	}

	@Transactional(readOnly = false)
	public void saveUser(MainUser mainUser) {
		if (StringUtils.isBlank(mainUser.getId())) {
			mainUser.preInsert();
			userDao.insert(mainUser);
			UserAccount userAccount = new UserAccount();
			userAccount.setBalance(0.0);
			userAccount.setUserId(mainUser.getId());
			accountDao.insert(userAccount);
		} else {
			// 清除原用户机构用户缓存
			MainUser oldUser = userDao.get(mainUser.getId());
			if (oldUser.getOffice() != null && oldUser.getOffice().getId() != null) {
				CacheUtils.remove(UserUtils.USER_CACHE,
						UserUtils.USER_CACHE_LIST_BY_OFFICE_ID_ + oldUser.getOffice().getId());
			}
			// 更新用户数据
			mainUser.preUpdate();
			userDao.update(mainUser);
		}
		if (StringUtils.isNotBlank(mainUser.getId())) {
			// 更新用户与角色关联
			userDao.deleteUserRole(mainUser);
			if (mainUser.getRoleList() != null && mainUser.getRoleList().size() > 0) {
				userDao.insertUserRole(mainUser);
			} 
			// 清除用户缓存
			UserUtils.clearCache(mainUser);
			// // 清除权限缓存
			// systemRealm.clearAllCachedAuthorizationInfo();
		}
	}

	@Transactional(readOnly = false)
	public void updateUserInfo(MainUser mainUser) {
		mainUser.preUpdate();
		userDao.updateUserInfo(mainUser);
		// 清除用户缓存
		UserUtils.clearCache(mainUser);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void deleteUser(MainUser mainUser) {
		userDao.delete(mainUser);
		// 同步到Activiti
		// deleteActivitiUser(mainUser);
		// 清除用户缓存
		UserUtils.clearCache(mainUser);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void updatePasswordById(String id, String loginName, String newPassword) {
		MainUser mainUser = new MainUser(id);
		mainUser.setPassword(entryptPassword(newPassword));
		userDao.updatePasswordById(mainUser);
		// 清除用户缓存
		mainUser.setLoginName(loginName);
		UserUtils.clearCache(mainUser);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void updateUserLoginInfo(MainUser mainUser) {
		// 保存上次登录信息
		// mainUser.setOldLoginIp(mainUser.getLoginIp());
		// mainUser.setOldLoginDate(mainUser.getLoginDate());
		// 更新本次登录信息
		// mainUser.setLoginIp(StringUtils.getRemoteAddr(Servlets.getRequest()));
		// mainUser.setLoginDate(new Date());
		// userDao.updateLoginInfo(mainUser);
	}

	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 */
	public static String entryptPassword(String plainPassword) {
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);
	}

	/**
	 * 验证密码
	 * 
	 * @param plainPassword
	 *            明文密码
	 * @param password
	 *            密文密码
	 * @return 验证成功返回true
	 */
	public static boolean validatePassword(String plainPassword, String password) {
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = Encodes.decodeHex(password.substring(0, 16));
		byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword));
	}

	/**
	 * 获得活动会话
	 * 
	 * @return
	 */
	public Collection<Session> getActiveSessions() {
		return sessionDao.getActiveSessions(false);
	}

	// -- Role Service --//

	public Role getRole(String id) {
		return roleDao.get(id);
	}

	public Role getRoleByName(String name) {
		Role r = new Role();
		r.setName(name);
		return roleDao.getByName(r);
	}

	public Role getRoleByEnname(String enname) {
		Role r = new Role();
		r.setEnname(enname);
		return roleDao.getByEnname(r);
	}

	public List<Role> findRole(Role role) {
		return roleDao.findList(role);
	}

	public List<Role> findAllRole() {
		return UserUtils.getRoleList();
	}

	@Transactional(readOnly = false)
	public void saveRole(Role role) {
		if (StringUtils.isBlank(role.getId())) {
			role.preInsert();
			roleDao.insert(role);
			// 同步到Activiti
			// saveActivitiGroup(role);
		} else {
			role.preUpdate();
			roleDao.update(role);
		}
		// 更新角色与菜单关联
		roleDao.deleteRoleMenu(role);
		if (role.getMenuList().size() > 0) {
			roleDao.insertRoleMenu(role);
		}
		// 更新角色与部门关联
		roleDao.deleteRoleOffice(role);
		if (role.getOfficeList().size() > 0) {
			roleDao.insertRoleOffice(role);
		}
		// 同步到Activiti
		// saveActivitiGroup(role);
		// 清除用户角色缓存
		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void deleteRole(Role role) {
		roleDao.delete(role);
		// 同步到Activiti
//		deleteActivitiGroup(role);
		// 清除用户角色缓存
		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public Boolean outUserInRole(Role role, MainUser mainUser) {
		List<Role> roles = mainUser.getRoleList();
		for (Role e : roles) {
			if (e.getId().equals(role.getId())) {
				roles.remove(e);
				saveUser(mainUser);
				return true;
			}
		}
		return false;
	}

	@Transactional(readOnly = false)
	public MainUser assignUserToRole(Role role, MainUser mainUser) {
		if (mainUser == null) {
			return null;
		}
		List<String> roleIds = mainUser.getRoleIdList();
		if (roleIds.contains(role.getId())) {
			return null;
		}
		mainUser.getRoleList().add(role);
		saveUser(mainUser);
		return mainUser;
	}

	// -- Menu Service --//

	public Menu getMenu(String id) {
		return menuDao.get(id);
	}

	public List<Menu> findAllMenu() {
		return UserUtils.getMenuList();
	}

	@Transactional(readOnly = false)
	public void saveMenu(Menu menu) {

		// 获取父节点实体
		menu.setParent(this.getMenu(menu.getParent().getId()));

		// 获取修改前的parentIds，用于更新子节点的parentIds
		String oldParentIds = menu.getParentIds();

		// 设置新的父节点串
		menu.setParentIds(menu.getParent().getParentIds() + menu.getParent().getId() + ",");

		// 保存或更新实体
		if (StringUtils.isBlank(menu.getId())) {
			menu.preInsert();
			menuDao.insert(menu);
		} else {
			menu.preUpdate();
			menuDao.update(menu);
		}

		// 更新子节点 parentIds
		Menu m = new Menu();
		m.setParentIds("%," + menu.getId() + ",%");
		List<Menu> list = menuDao.findByParentIdsLike(m);
		for (Menu e : list) {
			e.setParentIds(e.getParentIds().replace(oldParentIds, menu.getParentIds()));
			menuDao.updateParentIds(e);
		}
		// 清除用户菜单缓存
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
		CacheUtils.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}

	@Transactional(readOnly = false)
	public void updateMenuSort(Menu menu) {
		menuDao.updateSort(menu);
		// 清除用户菜单缓存
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
		CacheUtils.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}

	@Transactional(readOnly = false)
	public void deleteMenu(Menu menu) {
		menuDao.delete(menu);
		// 清除用户菜单缓存
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
		// // 清除权限缓存
		// systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
		CacheUtils.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}

	/**
	 * 获取Key加载信息
	 */
	public static boolean printKeyLoadMessage() {
		StringBuilder sb = new StringBuilder();
		sb.append("\r\n======================================================================\r\n");
		System.out.println(sb.toString());
		return true;
	}


	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		
	}

}
